package com.whale.cloud.util;


import org.codehaus.jettison.json.JSONTokener;

import java.util.HashMap;

public class XMLTokener
        extends JSONTokener
{
    public static final HashMap entity = new HashMap(8);

    static
    {
        entity.put("amp", XML.AMP);
        entity.put("apos", XML.APOS);
        entity.put("gt", XML.GT);
        entity.put("lt", XML.LT);
        entity.put("quot", XML.QUOT);
    }

    public XMLTokener(String s)
    {
        super(s);
    }

    public String nextCDATA()
    {
        StringBuffer sb = new StringBuffer();
        int i;
        do
        {
            char c = next();
            if (c == 0) {
                return null;
            }
            sb.append(c);
            i = sb.length() - 3;
        } while ((i < 0) || (sb.charAt(i) != ']') || (sb.charAt(i + 1) != ']') || (sb.charAt(i + 2) != '>'));
        sb.setLength(i);
        return sb.toString();
    }

    public Object nextContent()
    {
        char c;
        do
        {
            c = next();
        } while (Character.isWhitespace(c));
        if (c == 0) {
            return null;
        }
        if (c == '<') {
            return XML.LT;
        }
        StringBuffer sb = new StringBuffer();
        for (;;)
        {
            if ((c == '<') || (c == 0))
            {
                back();
                return sb.toString().trim();
            }
            if (c == '&') {
                sb.append(nextEntity(c));
            } else {
                sb.append(c);
            }
            c = next();
        }
    }

    public Object nextEntity(char a)
    {
        StringBuffer sb = new StringBuffer();
        for (;;)
        {
            char c = next();
            if ((Character.isLetterOrDigit(c)) || (c == '#'))
            {
                sb.append(Character.toLowerCase(c));
            }
            else
            {
                if (c == ';') {
                    break;
                }
                return null;
            }
        }
        String s = sb.toString();
        Object e = entity.get(s);
        return a + s + ";";
    }

    public Object nextMeta()
    {
        char c;
        do
        {
            c = next();
        } while (Character.isWhitespace(c));
        switch (c)
        {
            case '\000':
                return null;
            case '<':
                return XML.LT;
            case '>':
                return XML.GT;
            case '/':
                return XML.SLASH;
            case '=':
                return XML.EQ;
            case '!':
                return XML.BANG;
            case '?':
                return XML.QUEST;
            case '"':
            case '\'':
                char q = c;
                do
                {
                    c = next();
                    if (c == 0) {
                        return null;
                    }
                } while (c != q);
                return Boolean.TRUE;
        }
        for (;;)
        {
            c = next();
            if (Character.isWhitespace(c)) {
                return Boolean.TRUE;
            }
            switch (c)
            {
                case '\000':
                case '!':
                case '"':
                case '\'':
                case '/':
                case '<':
                case '=':
                case '>':
                case '?':
                    back();
                    return Boolean.TRUE;
            }
        }
    }

    public Object nextToken()
    {
        char c;
        do
        {
            c = next();
        } while (Character.isWhitespace(c));
        switch (c)
        {
            case '\000':
                return null;
            case '<':
                return null;
            case '>':
                return XML.GT;
            case '/':
                return XML.SLASH;
            case '=':
                return XML.EQ;
            case '!':
                return XML.BANG;
            case '?':
                return XML.QUEST;
            case '"':
            case '\'':
                char q = c;
                StringBuffer sb = new StringBuffer();
                for (;;)
                {
                    c = next();
                    if (c == 0) {
                        return null;
                    }
                    if (c == q) {
                        return sb.toString();
                    }
                    if (c == '&') {
                        sb.append(nextEntity(c));
                    } else {
                        sb.append(c);
                    }
                }
        }
        StringBuffer sb = new StringBuffer();
        for (;;)
        {
            sb.append(c);
            c = next();
            if (Character.isWhitespace(c)) {
                return sb.toString();
            }
            switch (c)
            {
                case '\000':
                case '!':
                case '/':
                case '=':
                case '>':
                case '?':
                case '[':
                case ']':
                    back();
                    return sb.toString();
                case '"':
                case '\'':
                case '<':
                    return null;
            }
        }
    }
}

